package com.xuanyuanxinyu.core.bus;

import android.os.Looper;

import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;

import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * IgnoreStateChange 标志的函数，会忽略由于Livedata的生命周期从onInative  切换到 Inactive 会尝试更新一次最新的值的
 * Forever 表示的都是需要用户自己手动删除observer的
 * Sticky 粘性消息，一监听就会收当前livedata的mdata的值
 */
public class SimplePeekLiveData<T> extends LiveData<T> {

    private final int START_VERSION = -1;

    private final AtomicInteger currentVersion = new AtomicInteger(START_VERSION);

    /**
     * onInative 状态为true
     */
    private final AtomicBoolean stateChange = new AtomicBoolean();

    public void observeIgnoreStateChange(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        super.observe(owner, createObserverWrapper(observer, currentVersion.get(), true));
    }

    public void observeStickyIgnoreStateChange(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        super.observe(owner, createObserverWrapper(observer, START_VERSION, true));
    }

    @Override
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        super.observe(owner, createObserverWrapper(observer, currentVersion.get(), false));
    }

    @Override
    public void observeForever(@NonNull Observer<? super T> observer) {
        super.observeForever(createObserverWrapper(observer, currentVersion.get(), false));
    }

    public void observeSticky(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        super.observe(owner, createObserverWrapper(observer, START_VERSION, false));
    }

    public void observeForeverSticky(@NonNull Observer<? super T> observer) {
        super.observeForever(createObserverWrapper(observer, START_VERSION, false));
    }

    @Override
    protected void onActive() {
        super.onActive();
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        stateChange.getAndSet(true);
    }

    @Override
    public void setValue(T value) {
        currentVersion.getAndIncrement();
        boolean isMainThread = Looper.getMainLooper().getThread() == Thread.currentThread();
        if (isMainThread) {
            super.setValue(value);
        } else {
            super.postValue(value);
        }
    }

    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    private class ObserverWrapper implements Observer<T> {
        private final Observer<? super T> observer;
        private final int mVersion;
        private final boolean isIgnoreLifeLastUpdate;

        public ObserverWrapper(@NonNull Observer<? super T> observer, int mVersion, boolean isIgnoreLifeLastUpdate) {
            this.observer = observer;
            this.mVersion = mVersion;
            this.isIgnoreLifeLastUpdate = isIgnoreLifeLastUpdate;
        }

        @Override
        public void onChanged(T t) {
            if (currentVersion.get() > mVersion) {
                //设置忽略，状态是从onInactive 切换到 onActive 只有感知生命周期才会有用
                if (isIgnoreLifeLastUpdate && stateChange.get()) {
                    stateChange.getAndSet(false);
                    return;
                }
                try {
                    observer.onChanged(t);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        @SuppressWarnings("unchecked")
        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            ObserverWrapper that = (ObserverWrapper) o;
            return Objects.equals(observer, that.observer);
        }

        @Override
        public int hashCode() {
            return Objects.hash(observer);
        }
    }

    private ObserverWrapper createObserverWrapper(@NonNull Observer<? super T> observer, int version, boolean isIgnoreLifeLastUpdate) {
        return new ObserverWrapper(observer, version, isIgnoreLifeLastUpdate);
    }

    @Override
    public void removeObserver(@NonNull Observer<? super T> observer) {
        if (observer.getClass().isAssignableFrom(ObserverWrapper.class)) {
            super.removeObserver(observer);
        } else {
            super.removeObserver(createObserverWrapper(observer, START_VERSION, false));
        }
    }
}
